The present invention relates to a method and an associated apparatus for performing multiple tasks simultaneously on a computer.
Most modern operating systems have native multi-tasking or multi-threading capabilities, that is, multi-threading capabilities built into the operating system. Notable exceptions are versions of the Macintosh Operating System (MacOS) prior to OS X, which possess little or no multi-threading capabilities. Unfortunately, the multi-threading capabilities provided differ depending on the operating system and hardware platform. Many platforms impose limits on the total number of threads that can exist simultaneously, and some platforms cannot multi-thread at all.
In order to properly understand the problems introduced by threading in the software and their solutions, it is necessary to understand the general approach to multi-threading and the specific approach used by most platform-native threading systems.
To perform multiple processing tasks at once, an obvious solution is to provide multiple sets of processing circuitry in the computer system. However, the typical desktop computer only has one processor, and even high-end workstations only have between one and four processors.
The software based solution is time slicing, that is, dividing the processor's time into a series of tiny slices, and devoting each slice in turn to a different task or thread. Typically, each thread is allowed to run for between 3 ms and 30 ms depending on the operating system, at which time that thread is suspended and another thread is allowed to run. The operating system usually uses the processor's timer interrupt to periodically interrupt the currently executing thread and invoke the operating system's thread scheduler, a piece of software that saves the current thread's state or execution context, selects a new thread to run, restores the new thread's saved execution context, and then allows the processor to resume normal execution. This process is known as a context switch.
In addition to occurring when a time slice expires, a context switch can also occur if the thread enters a wait state, a state in which the thread has nothing to do until a specific event occurs. When a thread enters such a state, the thread scheduler is invoked and a context switch occurs so that some other thread may use the remainder of the time slice.
A typical event that can cause a thread to enter a wait state occurs when the thread attempts to access memory that has been paged to disk. The operating system suspends the thread until the memory system has had a chance to page in the memory. Other events causing a thread to enter a wait state are the thread's checking for user input and the thread's attempting to read from the disk. In the latter case, the operating system suspends the thread until the disk read completes, allowing other threads to perform processing tasks while the first thread waits for the data to be read from disk. Yet another event that can induce a thread to enter a wait state occurs when the thread specifically yields the remainder of its time slice. This may happen if, for example, the thread has nothing more to do for a while.
Because context switches can occur with great frequency, it is critical for the context switch operating to be extremely fast Many operating systems place limits on the number of threads that can exist in the system. Windows 95 has a maximum of about 150–200 threads before system becomes unstable, whereas BeOS has a maximum of 4096 threads per processor. Such a limitation in the number of threads is a result of an operating system pre-allocating, for performance reasons, a fixed-size chunk of memory for the thread table when the system boots.
Standard non-interpreted programming languages compile human-readable source code into machine-readable code, or machine language code directly readable by the processor.
An interpreted language, on the other hand, compiles human-readable source code into an interpreter-readable code, or bytecode. A software program called an interpreter, written in machine language, later reads the bytecode and instructs the processor to perform the appropriate operations.
A key advantage of an interpreted language is that the bytecode can be designed so that it is machine independent, allowing a program written in the language and compiled into bytecode to run on any operating system and hardware platform that an interpreter has been written for.
When developing an interpreted language that must run identically on all platforms, relying on a platform's native multi-threading can be problematic at best. The goal of a cross-platform interpreted programming language is to make it possible to develop a program in the language on one platform, and then run that program unchanged on any other platform supported by the language. Java is one example of an attempt to create such a language.
Unfortunately, if such an application must multi-thread, use of native multi-threading capabilities immediately limits the platforms on which the application can run. The application program is immediately precluded from running on most versions of the MacOS (which has no threading ability), and depending on how many simultaneous threads of execution the application program requires, it may be precluded from running on Windows 95 (maximum of about 150–200 threads), BeOS (maximum of 4096 threads per processor), or other platforms.